const createHash = require('./node_modules/webpack/lib/util/createHash');

const validateOptions = require('schema-utils');

const schema = {
  'title': 'HashedModuleIdsPluginOptions',
  'type': 'object',
  'additionalProperties': false,
  'properties': {
    'context': {
      'description': 'The context directory for creating names.',
      'type': 'string',
      'absolutePath': true
    },
    'hashDigest': {
      'description': 'The encoding to use when generating the hash, defaults to \'base64\'. All encodings from Node.JS\' hash.digest are supported.',
      'enum': ['hex', 'latin1', 'base64']
    },
    'hashDigestLength': {
      'description': 'The prefix length of the hash digest to use, defaults to 4.',
      'type': 'number',
      'minimum': 1
    },
    'hashFunction': {
      'description': 'The hashing algorithm to use, defaults to \'md5\'. All functions from Node.JS\' crypto.createHash are supported.',
      'type': 'string',
      'minLength': 1
    }
  }
};

class ModuleIds {
  constructor(options) {
    if (!options) options = {};

    validateOptions(schema, options, 'Hashed Module Ids Plugin');
    this.options = Object.assign(
      {
        hashFunction: 'sha256',
        hashDigest: 'hex',
        hashDigestLength: 20
      },
      options
    );
  }

  apply(compiler) {
    const options = this.options;
    compiler.hooks.compilation.tap('compilation', (compilation) => {
      compilation.hooks.beforeModuleIds.tap('beforeModuleIds', (modules) => {
        const usedIds = new Set();
        console.error('--------------')
        for (const module of modules) {
          if (module.libIdent) {
            const path = module.libIdent({
              context: compiler.options.context
            });
            if (path.lastIndexOf('entry-lib.js')!=-1) {
                continue;
            }
            const hash = createHash(options.hashFunction);
            hash.update(path);
            const hashId = (hash.digest(
              options.hashDigest
            ));
            let len = options.hashDigestLength;
            while (usedIds.has(hashId.substr(0, len))) len++;
            module.id = hashId.substr(0, len);
            usedIds.add(module.id);
            console.info(module.id, path);
          }
        }
        console.error('--------------')
      });

      compilation.hooks.optimizeChunkIds.tap('chunkIds', (chunks) => {
        chunks.forEach((chunk) => {
          // if (module.dependencies[0]) {
          //   if (module.dependencies[0].originModule) {
          //     console.log(module.id + ':', module.dependencies[0].originModule.issuer.rawRequest);
          //   }
          // } else {
          //   console.error(module.id + ':', module.dependencies[0])
          // }
          // console.error(chunk.name)
        });
      })
    })
  }
}

module.exports = ModuleIds;
